package com.doge.walknovel.business.reader.menus

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.widget.SeekBar
import androidx.core.view.setPadding
import androidx.fragment.app.activityViewModels
import com.doge.wnpro.R
import com.doge.walknovel.analysis.analysisEvent
import com.doge.walknovel.analysis.light_changed
import com.doge.walknovel.api.model.NovelDetailInfo
import com.doge.walknovel.api.model.NovelInfo
import com.doge.walknovel.api.model.ChapterInfo
import com.doge.walknovel.business.novel.NovelDetailViewModel
import com.doge.walknovel.business.novel.NovelDetailViewModelFactory
import com.doge.walknovel.business.home.library.LibraryRepository
import com.doge.walknovel.business.novel.NovelRefer
import com.doge.walknovel.business.reader.ReaderViewModel
import com.doge.walknovel.business.reader.comments.ReaderCommentsDialogFragment
import com.doge.walknovel.core.BaseFragment
import com.doge.wnpro.databinding.FragmentReaderMenusBinding
import com.doge.walknovel.utils.*
import kotlin.math.max

class ReaderMenuFragment : BaseFragment() {
    private var innerBinding: FragmentReaderMenusBinding? = null
    private val binding get() = innerBinding!!
    private val refer by lazy { arguments?.getString(NovelRefer.EXTRA_REFER)!! }
    private val referId by lazy { arguments?.getInt(NovelRefer.EXTRA_REFER_ID) }
    private val novelId by lazy { arguments?.getInt(EXTRA_NOVEL_ID)!! }
    private val bookViewModel: NovelDetailViewModel by activityViewModels {
        NovelDetailViewModelFactory(novelId, "reader$refer", referId)
    }
    private val viewModel: ReaderViewModel by activityViewModels()
    private var currentChapter: ChapterInfo? = null
    private var bookDetail: NovelDetailInfo? = null
    private var animator: ValueAnimator? = null
    private var isAnimating = false
    private var isDisplaying = false
    private var clickedLightMode: Boolean? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        innerBinding =
            innerBinding ?: FragmentReaderMenusBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.menusPanel.visibility = View.GONE
        binding.top.translationY = (-100).dp.toFloat()
        binding.bottom.translationY = (180).dp.toFloat()
        binding.outside.alpha = 0f
        binding.add.setText(
            if (LibraryRepository.get()
                    .containsNovel(novelId)
            ) R.string.in_library else R.string.add_add_books
        )
        binding.readerLight.setImageResource(if (!ReaderHelper.light) R.mipmap.reader_light_on else R.mipmap.reader_light_off)
        initialViews()
        systemWindowInsetsTop.observe(viewLifecycleOwner) {
            binding.fitsSys.setPadding(it / 2)
        }
        viewModel.centerEvents.observe(viewLifecycleOwner) {
            it?.let { display() }
        }
        viewModel.readerDisplayingChapter.observe(viewLifecycleOwner) {
            currentChapter = it
        }
        bookViewModel.bookDetail.observe(viewLifecycleOwner) {
            bookDetail = it
            updateProgress()
        }

        bookViewModel.requestNovelInfo()
    }

    private fun initialViews() {
        binding.back.setOnClickCallback { activity?.finish() }
        binding.outside.setOnClickCallback {
            hide()
        }
        binding.add.setOnClickCallback {
            LibraryRepository.get().requestAddNovel(NovelInfo.form(bookDetail))
            binding.add.setText(R.string.in_library)
        }
        binding.readerChapters.setOnClickCallback {
            ReaderChapterDialogFragment.newInstance(novelId, refer, referId).show(activity?.supportFragmentManager)
            hide()
        }
        binding.readerTextSize.setOnClickCallback {
            binding.adjust.display()
        }
        binding.readerLight.setOnClickCallback {
            val current = ReaderHelper.light
            ReaderHelper.changeLight(!current)
            clickedLightMode = !current
            binding.readerLight.setImageResource(if (!current) R.mipmap.reader_light_on else R.mipmap.reader_light_off)
        }
        binding.readerComments.setOnClickCallback {
            hide()
            ReaderCommentsDialogFragment.newInstance(novelId, currentChapter?.chapterId, refer, referId)
                ?.show(childFragmentManager)
        }
        binding.readerProgress.setOnSeekBarChangeListener(seekBarListener)
    }

    private fun hide() {
        if (!isDisplaying) return
        if (isAnimating) return
        isAnimating = true
        isDisplaying = false
        activity?.useTranslucentStatusBar(true)
        animator = ValueAnimator.ofFloat(1f, 0f).apply {
            interpolator = DecelerateInterpolator(2f)
            startDelay = 10
            duration = 300
            addUpdateListener {
                val percent = it.animatedValue as Float

                binding.top.translationY = (-100).dp * (1 - percent)
                binding.bottom.translationY = (180).dp * (1 - percent)
                binding.outside.alpha = percent
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator?) {
                    isAnimating = false
                    binding.menusPanel.visibility = View.GONE
                    binding.adjust.visibility = View.GONE
                }
            })
        }
        animator?.start()

        updateProgress()
        binding.adjust.binding.layFont.analysisUsingTypeface()
        analysisUsingLight()
    }

    private fun display() {
        if (isDisplaying) return
        if (isAnimating) return
        isAnimating = true
        isDisplaying = true
        binding.menusPanel.visibility = View.VISIBLE
        activity?.useTranslucentStatusBar(false)
        animator = ValueAnimator.ofFloat(0f, 1f).apply {
            interpolator = DecelerateInterpolator(2f)
            startDelay = 10
            duration = 300
            addUpdateListener {
                val percent = it.animatedValue as Float

                binding.top.translationY = (-100).dp * (1 - percent)
                binding.bottom.translationY = (180).dp * (1 - percent)
                binding.outside.alpha = percent
            }
            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator?) {
                    isAnimating = false
                }
            })
        }
        animator?.start()
    }


    override fun onDestroyView() {
        super.onDestroyView()
        animator?.cancel()
        binding.back.setOnClickListener(null)
        binding.outside.setOnClickListener(null)
        binding.add.setOnClickListener(null)
        binding.readerProgress.setOnSeekBarChangeListener(null)
        binding.readerChapters.setOnClickListener(null)
        binding.readerTextSize.setOnClickListener(null)
        binding.readerLight.setOnClickListener(null)
        binding.readerComments.setOnClickListener(null)
        innerBinding = null
    }

    private fun updateProgress() {
        log("updateProgress bookDetail $bookDetail chapter $currentChapter")
        val novel = bookDetail ?: return
        val chapter = currentChapter ?: ChapterInfo.NONE

        binding.readerProgress.visibility = View.VISIBLE
        binding.progressText.visibility = View.VISIBLE
        val totalCount = max(1, novel.chapterCount ?: 1)
        binding.readerProgress.max = totalCount
        val currentIdx = (chapter.chapterIndex ?: 0)
        val percent = currentIdx.toFloat() / totalCount
        val progress: Int = (percent * binding.readerProgress.max).toInt()
        log("updateProgress currentIdx $currentIdx totalCount $totalCount progress $progress")
        binding.readerProgress.progress = progress
        binding.progressText.text = percent.percentage
    }



    private val seekBarListener = object : SeekBar.OnSeekBarChangeListener {
        override fun onStopTrackingTouch(seekBar: SeekBar?) {
            log("readerProgress onStopTrackingTouch ${seekBar?.progress} ${seekBar?.max}")
            val total = seekBar?.max ?: return
            val progress = seekBar.progress
            val percent: Float = progress.toFloat() / total
            binding.progressText.text = percent.percentage
            viewModel.redirectToChapterProgress(percent)
        }

        override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
            log("readerProgress onProgressChanged progress $progress fromUser $fromUser")
        }

        override fun onStartTrackingTouch(seekBar: SeekBar?) {
            log("readerProgress onStartTrackingTouch")
        }
    }

    private fun analysisUsingLight() {
        val usingLightMode = clickedLightMode ?: return
        analysisEvent("${light_changed}_${if (usingLightMode) "Light" else "Dark"}")
        clickedLightMode = null
    }

    companion object {
        private const val EXTRA_NOVEL_ID = "novelId"
        fun newInstance(novelId: Int,
                        refer: String, referId: Int? = null): ReaderMenuFragment {
            return ReaderMenuFragment().apply {
                arguments = Bundle().apply {
                    putInt(EXTRA_NOVEL_ID, novelId)
                    putString(NovelRefer.EXTRA_REFER, refer)
                    referId?.let { putInt(NovelRefer.EXTRA_REFER_ID, referId) }
                }
            }
        }
    }
}